package com.es.demo.task;

import com.sun.istack.internal.NotNull;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Map;
import java.util.Objects;


/**
 * 类名: SpringContextUtil
 * 描述：获取bean的工具类，可用于在线程里面获取bean
 * 时间: 2023年05月16日18:18:49
 * @author sunlingtong
 */
@Component("SpringContextUtil")
public class SpringContextUtil implements ApplicationContextAware {


    public static final String LOCAL_PROFILE = "local";

    public static final String DEV_PROFILE = "dev";

    public static final String TEST_PROFILE = "test";

    public static final String PRO_PROFILE = "pro";

    private static ApplicationContext applicationContext = null;

    private SpringContextUtil() {
        super();
    }

    public static synchronized ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    // 下面的这个方法上加了@Override注解，原因是继承ApplicationContextAware接口是必须实现的方法
    @Override
    public void setApplicationContext(@NotNull ApplicationContext applicationContext)
            throws BeansException {
        synchronized (this) {
            if (Objects.isNull(SpringContextUtil.applicationContext)) {
                SpringContextUtil.applicationContext = applicationContext;
            }
        }
    }

    /**
     * @param beanName bean名称
     * @Description: 获取spring容器中的bean, 通过bean名称获取
     * @return: Object 返回Object,需要做强制类型转换
     * @time: 2023-02-28 10:45:07
     */
    public static Object getBean(String beanName) {
        return applicationContext.getBean(beanName);
    }

    /**
     * @param beanClass bean 类型
     * @Description: 获取spring容器中的bean, 通过bean类型获取
     * @return: T 返回指定类型的bean实例
     * @time: 2023-02-28 10:46:31
     */
    public static <T> T getBean(Class<T> beanClass) {
        return applicationContext.getBean(beanClass);
    }

    /**
     * @param beanName  bean 名称
     * @param beanClass bean 类型
     * @Description: 获取spring容器中的bean, 通过bean名称和bean类型精确获取
     * @return: T 返回指定类型的bean实例
     * @time: 2023-02-28 10:47:45
     */
    public static <T> T getBean(String beanName, Class<T> beanClass) {
        return applicationContext.getBean(beanName, beanClass);
    }

    /**
     * @param beanClass bean 类型
     * @Description: 根据 bean 的 class 来查找所有的对象（包括子类）
     * @return: T 返回指定类型的bean实例
     * @time: 2023-02-28 10:47:45
     */
    public static <T> Map<String, T> getBeansByClass(Class<T> beanClass) {
        return applicationContext.getBeansOfType(beanClass);
    }

    /**
     * 是否包含bean
     *
     * @param beanName bean 名称
     */
    public static boolean containsBean(String beanName) {
        return applicationContext.containsBean(beanName);
    }

    /**
     * 获取HttpServletRequest
     */
    public static HttpServletRequest getHttpServletRequest() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        return attributes.getRequest();
    }

    /**
     * 获取HttpSession
     */
    public static HttpSession getSession() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        return attributes.getRequest().getSession();
    }

    public static String getDomain() {
        HttpServletRequest request = getHttpServletRequest();
        StringBuffer url = request.getRequestURL();
        return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
    }

    /**
     * 获取请求头
     */
    public static String getOrigin() {
        HttpServletRequest request = getHttpServletRequest();
        return request.getHeader("Origin");
    }

    /**
     * 获取完整的请求URL
     */
    public static String getRequestUrl() {
        return getRequestUrl(getHttpServletRequest());
    }

    /**
     * 获取完整的请求URL
     */
    public static String getRequestUrl(HttpServletRequest request) {
        // 当前请求路径
        String currentUrl = request.getRequestURL().toString();
        // 请求参数
        String queryString = request.getQueryString();
        if (!ObjectUtils.isEmpty(queryString)) {
            currentUrl = currentUrl + "?" + queryString;
        }

        String result = "";
        try {
            result = URLDecoder.decode(currentUrl, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            // ignore
        }

        return result;
    }

    /**
     * 获取spring.profiles.active
     */
    public static String getProfile() {
        return getApplicationContext().getEnvironment().getActiveProfiles()[0];
    }

    /**
     * 判断是否为联调环境
     */
    public static boolean profileIsDev() {
        return DEV_PROFILE.equals(getProfile());
    }

    /**
     * 判断是否为本地开发环境
     */
    public static boolean profileIsLocal() {
        return LOCAL_PROFILE.equals(getProfile());
    }

    /**
     * 判断是否为测试环境
     */
    public static boolean profileIsTest() {
        return TEST_PROFILE.equals(getProfile());
    }

    /**
     * 判断是否为生产环境
     */
    public static boolean profileIsPro() {
        return PRO_PROFILE.equals(getProfile());
    }

    /**
     * 是否是 Linux 环境
     *
     * @return
     */
    public static boolean isLinux() {
        return System.getProperty("os.name").toLowerCase().contains("linux");
    }

    public static boolean isMac() {
        return System.getProperty("os.name").toLowerCase().contains("mac");
    }

    /**
     * 是否是 Windows 环境
     *
     * @return
     */
    public static boolean isWindows() {
        return System.getProperty("os.name").toLowerCase().contains("windows");
    }
}
